<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link href='/css/styles.css' rel='stylesheet' type='text/css' />
    <link href='/images/favicon.png' rel='shortcut icon' />
    <script src='/js/jquery.min.1.4.js'></script>
    <script src='/js/app.js'></script>
    <script src='/js/common.js'></script>
    
    <meta content='width=device-width, minimum-scale=1.0, maximum-scale=1.0' name='viewport' />
    <title>redis - 命令</title>
	<meta http-equiv="description" content="redis中文资料站，下载安装redis，查找redis常用命令（commands），选择适合的redis客户端方式，配置redis主从（master-slave），阅读redis官方文档，社区里了解更多redis信息，提交redis的bug。" />
	
  </head>
  <body class=''>
    <script src='/js/head.js'></script>
    <div class='text'>
      <h1 class='command'>
        <span id='command_name_span' class='name'></span>
        <span id='command_args_span' class='arg'></span>
      </h1>
      <article>
      	<aside>
        	<script type='text/javascript'>showCmdURL();</script>
        </aside>
        
        <div class='metadata'>
          <p><strong>加入版本 <span id='command_ver_span'></span>。</strong></p>
          <p><strong>时间复杂度：</strong> Depends on the script that is executed。</p>
        </div>
        
        <h2>EVAL简介</h2>
        
        <p><a href="/commands/eval.html">EVAL</a> 和 <a href="/commands/evalsha.html">EVALSHA</a> 命令是从 Redis 2.6.0 版本开始的，使用内置的 Lua 解释器，可以对 Lua 脚本进行求值。</p>
        
        <p><a href="/commands/eval.html">EVAL</a>的第一个参数是一段 Lua 5.1 脚本程序。
        这段Lua脚本不需要（也不应该）定义函数。它运行在 Redis 服务器中。</p>
        
        <p>
        	<a href="/commands/eval.html">EVAL</a>的第二个参数是参数的个数，后面的参数（从第三个参数），表示在脚本中所用到的那些 Redis 键(key)，这些键名参数可以在 Lua 中通过全局变量 <a href="/commands/keys.html">KEYS</a> 数组，用 1 为基址的形式访问( <code>KEYS[1]</code> ， <code>KEYS[2]</code> ，以此类推)。
        </p>
        
        <p>
        	在命令的最后，那些不是键名参数的附加参数 arg [arg ...] ，可以在 Lua 中通过全局变量 <code>ARGV</code> 数组访问，访问的形式和 KEYS 变量类似( <code>ARGV[1]</code> 、 <code>ARGV[2]</code> ，诸如此类)。
        </p>
        
        <p>举例说明：</p>
        
        <pre><code>&gt; eval &quot;return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}&quot; 2 key1 key2 first second&#x000A;1) &quot;key1&quot;&#x000A;2) &quot;key2&quot;&#x000A;3) &quot;first&quot;&#x000A;4) &quot;second&quot;&#x000A;</code></pre>
        
        <p>注：返回结果是Redis multi bulk replies的Lua数组，这是一个Redis的返回类型，您的客户端库可能会将他们转换成数组类型。</p>
        
        <p>这是从一个Lua脚本中使用两个不同的Lua函数来调用Redis的命令的例子：</p>
        
        <ul>
        <li><code>redis.call()</code></li>
        <li><code>redis.pcall()</code></li>
        </ul>
        
        <p><code>redis.call()</code> 与 <code>redis.pcall()</code>很类似, 他们唯一的区别是当redis命令执行结果返回错误时，
        	<code>redis.call()</code>将返回给调用者一个错误，而<code>redis.pcall()</code>会将捕获的错误以Lua表的形式返回
        </p>
        
        <p>
        	<code>redis.call()</code> 和 <code>redis.pcall()</code> 两个函数的参数可以是任意的 Redis 命令：
        </p>
        
        <pre><code>&gt; eval &quot;return redis.call(&#39;set&#39;,&#39;foo&#39;,&#39;bar&#39;)&quot; 0&#x000A;OK&#x000A;</code></pre>
        
        <p>
        	需要注意的是，上面这段脚本的确实现了将键 <code>foo</code> 的值设为 bar 的目的，但是，它违反了 <a href="/commands/eval.html">EVAL</a> 命令的语义，因为脚本里使用的所有键都应该由 KEYS 数组来传递，就像这样：
        </p>
        
        <pre><code>&gt; eval &quot;return redis.call(&#39;set&#39;,KEYS[1],&#39;bar&#39;)&quot; 1 foo&#x000A;OK&#x000A;</code></pre>
        
        <p>
        	要求使用正确的形式来传递键(key)是有原因的，因为不仅仅是 <a href="/commands/eval.html">EVAL</a> 这个命令，所有的 Redis 命令，在执行之前都会被分析，籍此来确定命令会对哪些键进行操作。
        </p>
        
        <p>
        	因此，对于 <a href="/commands/eval.html">EVAL</a> 命令来说，必须使用正确的形式来传递键，才能确保分析工作正确地执行。
        	除此之外，使用正确的形式来传递键还有很多其他好处，它的一个特别重要的用途就是确保 Redis 集群可以将你的请求发送到正确的集群节点。
        	(对 Redis 集群的工作还在进行当中，但是脚本功能被设计成可以与集群功能保持兼容。)不过，这条规矩并不是强制性的，
        	从而使得用户有机会滥用(abuse) Redis 单实例配置(single instance configuration)，代价是这样写出的脚本不能被 Redis 集群所兼容。
        </p>
        
        <p>Lua 脚本能返回一个值，这个值能按照一组转换规则从Lua转换成redis的返回类型。</p>
        
        <h2>Lua 数据类型和 Redis 数据类型之间转换</h2>
        
        <p>
        	当 Lua 通过 call() 或 pcall() 函数执行 Redis 命令的时候，命令的返回值会被转换成 Lua 数据结构。
        同样地，当 Lua 脚本在 Redis 内置的解释器里运行时，Lua 脚本的返回值也会被转换成 Redis 协议(protocol)，然后由 <a href="/commands/eval.html">EVAL</a> 将值返回给客户端。
        </p>
        
        <p>数据类型之间的转换遵循这样一个设计原则：如果将一个 Redis 值转换成 Lua 值，之后再将转换所得的 Lua 值转换回 Redis 值，那么这个转换所得的 Redis 值应该和最初时的 Redis 值一样。</p>
        
        <p>换句话说， Lua 类型和 Redis 类型之间存在着一一对应的转换关系。</p>
        
        <p><strong>Redis 到 Lua</strong> 的转换表。</p>
        
        <ul>
        <li>Redis integer reply -&gt; Lua number</li>
        <li>Redis bulk reply -&gt; Lua string</li>
        <li>Redis multi bulk reply -&gt; Lua table (may have other Redis data types nested)</li>
        <li>Redis status reply -&gt; Lua table with a single <code>ok</code> field containing the status</li>
        <li>Redis error reply -&gt; Lua table with a single <code>err</code> field containing the error</li>
        <li>Redis Nil bulk reply and Nil multi bulk reply -&gt; Lua false boolean type</li>
        </ul>
        
        <p><strong>Lua 到 Redis</strong> 的转换表。</p>
        
        <ul>
        <li>Lua number -&gt; Redis integer reply (the number is converted into an integer)</li>
        <li>Lua string -&gt; Redis bulk reply</li>
        <li>Lua table (array) -&gt; Redis multi bulk reply (truncated to the first nil inside the Lua array if any)</li>
        <li>Lua table with a single <code>ok</code> field -&gt; Redis status reply</li>
        <li>Lua table with a single <code>err</code> field -&gt; Redis error reply</li>
        <li>Lua boolean false -&gt; Redis Nil bulk reply.</li>
        </ul>
        
        <p>从 Lua 转换到 Redis 有一条额外的规则，这条规则没有和它对应的从 Redis 转换到 Lua 的规则：</p>
        
        <ul>
        <li>Lua boolean true -&gt; Redis integer reply with value of 1.</li>
        </ul>
        
        <p>还有下面两点需要重点注意：</p>
        
        <ul>
        <li>
        	lua中整数和浮点数之间没有什么区别。因此，我们始终Lua的数字转换成整数的回复，这样将舍去小数部分。如果你想从Lua返回一个浮点数，你应该将它作为一个字符串（见比如<a href="/commands/zscore.html">ZSCORE</a>命令）。
        </li>
        <li>There is <a href="http://www.lua.org/pil/19.1.html">no simple way to have nils inside Lua arrays</a>, this is a result of Lua table semantics, so when Redis converts a Lua array into Redis protocol the conversion is stopped if a nil is encountered.</li>
        </ul>
        
        <p>以下是几个类型转换的例子：</p>
        
        <pre><code>&gt; eval &quot;return 10&quot; 0&#x000A;(integer) 10&#x000A;&#x000A;&gt; eval &quot;return {1,2,{3,&#39;Hello World!&#39;}}&quot; 0&#x000A;1) (integer) 1&#x000A;2) (integer) 2&#x000A;3) 1) (integer) 3&#x000A;   2) &quot;Hello World!&quot;&#x000A;&#x000A;&gt; eval &quot;return redis.call(&#39;get&#39;,&#39;foo&#39;)&quot; 0&#x000A;&quot;bar&quot;&#x000A;</code></pre>
        
        <p>
        	最后一个例子展示如果是Lua直接命令调用它是如何可以从<code>redis.call()</code>或<code>redis.pcall()</code>接收到准确的返回值。
        </p>
        
        <p>下面的列子我们可以看到浮点数和nil将怎么样处理：</p>
        
        <pre><code>&gt; eval &quot;return {1,2,3.3333,&#39;foo&#39;,nil,&#39;bar&#39;}&quot; 0&#x000A;1) (integer) 1&#x000A;2) (integer) 2&#x000A;3) (integer) 3&#x000A;4) &quot;foo&quot;&#x000A;</code></pre>
        
        <p>
        	正如你看到的 3.333 被转换成了3，并且 nil后面的字符串<em>bar</em>没有被返回回来。</p>
        
        <h2>返回redis类型的辅助函数</h2>
        
        <p>有两个辅助函数从Lua返回Redis的类型。</p>
        
        <ul>
        <li><code>redis.error_reply(error_string)</code> returns an error reply. This function simply returns the single field table with the <code>err</code> field set to the specified string for you.</li>
        <li><code>redis.status_reply(status_string)</code> returns a status reply. This function simply returns the single field table with the <code>ok</code> field set to the specified string for you.</li>
        </ul>
        
        <p>There is no difference between using the helper functions or directly returning the table with the specified format, so the following two forms are equivalent:</p>
        
        <pre><code>return {err=&quot;My Error&quot;}&#x000A;return redis.error_reply(&quot;My Error&quot;)&#x000A;</code></pre>
        
        <h2>脚本的原子性</h2>
        
        <p>
        	Redis 使用单个 Lua 解释器去运行所有脚本，并且， Redis 也保证脚本会以原子性(atomic)的方式执行：
        	当某个脚本正在运行的时候，不会有其他脚本或 Redis 命令被执行。
        	这和使用 <a href="/commands/multi.html">MULTI</a> / <a href="/commands/exec.html">EXEC</a> 包围的事务很类似。
        	在其他别的客户端看来，脚本的效果(effect)要么是不可见的(not visible)，要么就是已完成的(already completed)。
        </p>
        
        <p>另一方面，这也意味着，执行一个运行缓慢的脚本并不是一个好主意。写一个跑得很快很顺溜的脚本并不难，
        	因为脚本的运行开销(overhead)非常少，但是当你不得不使用一些跑得比较慢的脚本时，请小心，
        	因为当这些蜗牛脚本在慢吞吞地运行的时候，其他客户端会因为服务器正忙而无法执行命令。</p>
        
        <h2>错误处理</h2>
        
        <p>As already stated, calls to <code>redis.call()</code> resulting in a Redis command error
        will stop the execution of the script and will return the error, in a way that
        makes it obvious that the error was generated by a script:</p>
        
        <pre><code>&gt; del foo&#x000A;(integer) 1&#x000A;&gt; lpush foo a&#x000A;(integer) 1&#x000A;&gt; eval &quot;return redis.call(&#39;get&#39;,&#39;foo&#39;)&quot; 0&#x000A;(error) ERR Error running script (call to f_6b1bf486c81ceb7edf3c093f4c48582e38c0e791): ERR Operation against a key holding the wrong kind of value&#x000A;</code></pre>
        
        <p>Using the <code>redis.pcall()</code> command no error is raised, but an error object is
        returned in the format specified above (as a Lua table with an <code>err</code> field).
        The script can pass the exact error to the user by returning the error object
        returned by <code>redis.pcall()</code>.</p>
        
        <h2>Bandwidth and EVALSHA</h2>
        
        <p>The <a href="/commands/eval.html">EVAL</a> command forces you to send the script body again and again.
        Redis does not need to recompile the script every time as it uses an internal
        caching mechanism, however paying the cost of the additional bandwidth may not
        be optimal in many contexts.</p>
        
        <p>On the other hand, defining commands using a special command or via <code>redis.conf</code>
        would be a problem for a few reasons:</p>
        
        <ul>
        <li><p>Different instances may have different versions of a command implementation.</p></li>
        <li><p>Deployment is hard if there is to make sure all the instances contain a
        given command, especially in a distributed environment.</p></li>
        <li><p>Reading an application code the full semantic could not be clear since the
        application would call commands defined server side.</p></li>
        </ul>
        
        <p>In order to avoid these problems while avoiding the bandwidth penalty, Redis
        implements the <a href="/commands/evalsha.html">EVALSHA</a> command.</p>
        
        <p><a href="/commands/evalsha.html">EVALSHA</a> works exactly like <a href="/commands/eval.html">EVAL</a>, but instead of having a script as the first
        argument it has the SHA1 digest of a script.
        The behavior is the following:</p>
        
        <ul>
        <li><p>If the server still remembers a script with a matching SHA1 digest, the
        script is executed.</p></li>
        <li><p>If the server does not remember a script with this SHA1 digest, a special
        error is returned telling the client to use <a href="/commands/eval.html">EVAL</a> instead.</p></li>
        </ul>
        
        <p>Example:</p>
        
        <pre><code>&gt; set foo bar&#x000A;OK&#x000A;&gt; eval &quot;return redis.call(&#39;get&#39;,&#39;foo&#39;)&quot; 0&#x000A;&quot;bar&quot;&#x000A;&gt; evalsha 6b1bf486c81ceb7edf3c093f4c48582e38c0e791 0&#x000A;&quot;bar&quot;&#x000A;&gt; evalsha ffffffffffffffffffffffffffffffffffffffff 0&#x000A;(error) `NOSCRIPT` No matching script. Please use [EVAL](/commands/eval.html).&#x000A;</code></pre>
        
        <p>The client library implementation can always optimistically send <a href="/commands/evalsha.html">EVALSHA</a> under
        the hood even when the client actually calls <a href="/commands/eval.html">EVAL</a>, in the hope the script was
        already seen by the server.
        If the <code>NOSCRIPT</code> error is returned <a href="/commands/eval.html">EVAL</a> will be used instead.</p>
        
        <p>Passing keys and arguments as additional <a href="/commands/eval.html">EVAL</a> arguments is also very useful in
        this context as the script string remains constant and can be efficiently cached
        by Redis.</p>
        
        <h2>Script cache semantics</h2>
        
        <p>Executed scripts are guaranteed to be in the script cache <strong>forever</strong>.
        This means that if an <a href="/commands/eval.html">EVAL</a> is performed against a Redis instance all the
        subsequent <a href="/commands/evalsha.html">EVALSHA</a> calls will succeed.</p>
        
        <p>The only way to flush the script cache is by explicitly calling the SCRIPT
        FLUSH command, which will <em>completely flush</em> the scripts cache removing all the
        scripts executed so far.
        This is usually needed only when the instance is going to be instantiated for
        another customer or application in a cloud environment.</p>
        
        <p>The reason why scripts can be cached for long time is that it is unlikely for
        a well written application to have enough different scripts to cause memory
        problems.
        Every script is conceptually like the implementation of a new command, and even
        a large application will likely have just a few hundred of them.
        Even if the application is modified many times and scripts will change, the
        memory used is negligible.</p>
        
        <p>The fact that the user can count on Redis not removing scripts is semantically a
        very good thing.
        For instance an application with a persistent connection to Redis can be sure
        that if a script was sent once it is still in memory, so EVALSHA can be used
        against those scripts in a pipeline without the chance of an error being
        generated due to an unknown script (we&#39;ll see this problem in detail later).</p>
        
        <h2>The SCRIPT command</h2>
        
        <p>Redis offers a SCRIPT command that can be used in order to control the scripting
        subsystem.
        SCRIPT currently accepts three different commands:</p>
        
        <ul>
        <li><p>SCRIPT FLUSH.
        This command is the only way to force Redis to flush the scripts cache.
        It is most useful in a cloud environment where the same instance can be
        reassigned to a different user.
        It is also useful for testing client libraries&#39; implementations of the
        scripting feature.</p></li>
        <li><p>SCRIPT EXISTS <em>sha1</em> <em>sha2</em>... <em>shaN</em>.
        Given a list of SHA1 digests as arguments this command returns an array of
        1 or 0, where 1 means the specific SHA1 is recognized as a script already
        present in the scripting cache, while 0 means that a script with this SHA1
        was never seen before (or at least never seen after the latest SCRIPT FLUSH
        command).</p></li>
        <li><p>SCRIPT LOAD <em>script</em>.
        This command registers the specified script in the Redis script cache.
        The command is useful in all the contexts where we want to make sure that
        <a href="/commands/evalsha.html">EVALSHA</a> will not fail (for instance during a pipeline or MULTI/EXEC
        operation), without the need to actually execute the script.</p></li>
        <li><p>SCRIPT KILL.
        This command is the only way to interrupt a long-running script that reaches
        the configured maximum execution time for scripts.
        The SCRIPT KILL command can only be used with scripts that did not modify
        the dataset during their execution (since stopping a read-only script does
        not violate the scripting engine&#39;s guaranteed atomicity).
        See the next sections for more information about long running scripts.</p></li>
        </ul>
        
        <h2>Scripts as pure functions</h2>
        
        <p>A very important part of scripting is writing scripts that are pure functions.
        Scripts executed in a Redis instance are replicated on slaves by sending the
        script -- not the resulting commands.
        The same happens for the Append Only File.
        The reason is that sending a script to another Redis instance is much
        faster than sending the multiple commands the script generates, so if the
        client is sending many scripts to the master, converting the scripts into
        individual commands for the slave / AOF would result in too much bandwidth
        for the replication link or the Append Only File (and also too much CPU since
        dispatching a command received via network is a lot more work for Redis compared
        to dispatching a command invoked by Lua scripts).</p>
        
        <p>The only drawback with this approach is that scripts are required to have the
        following property:</p>
        
        <ul>
        <li>The script always evaluates the same Redis <em>write</em> commands with the same
        arguments given the same input data set.
        Operations performed by the script cannot depend on any hidden (non-explicit)
        information or state that may change as script execution proceeds or between
        different executions of the script, nor can it depend on any external input
        from I/O devices.</li>
        </ul>
        
        <p>Things like using the system time, calling Redis random commands like
        <a href="/commands/randomkey.html">RANDOMKEY</a>, or using Lua random number generator, could result into scripts
        that will not always evaluate in the same way.</p>
        
        <p>In order to enforce this behavior in scripts Redis does the following:</p>
        
        <ul>
        <li><p>Lua does not export commands to access the system time or other external
        state.</p></li>
        <li><p>Redis will block the script with an error if a script calls a Redis
        command able to alter the data set <strong>after</strong> a Redis <em>random</em> command like
        <a href="/commands/randomkey.html">RANDOMKEY</a>, <a href="/commands/srandmember.html">SRANDMEMBER</a>, <a href="/commands/time.html">TIME</a>.
        This means that if a script is read-only and does not modify the data set it
        is free to call those commands.
        Note that a <em>random command</em> does not necessarily mean a command that uses
        random numbers: any non-deterministic command is considered a random command
        (the best example in this regard is the <a href="/commands/time.html">TIME</a> command).</p></li>
        <li><p>Redis commands that may return elements in random order, like <a href="/commands/smembers.html">SMEMBERS</a>
        (because Redis Sets are <em>unordered</em>) have a different behavior when called
        from Lua, and undergo a silent lexicographical sorting filter before
        returning data to Lua scripts.
        So <code>redis.call(&quot;smembers&quot;,KEYS[1])</code> will always return the Set elements
        in the same order, while the same command invoked from normal clients may
        return different results even if the key contains exactly the same elements.</p></li>
        <li><p>Lua pseudo random number generation functions <code>math.random</code> and
        <code>math.randomseed</code> are modified in order to always have the same seed every
        time a new script is executed.
        This means that calling <code>math.random</code> will always generate the same sequence
        of numbers every time a script is executed if <code>math.randomseed</code> is not used.</p></li>
        </ul>
        
        <p>However the user is still able to write commands with random behavior using the
        following simple trick.
        Imagine I want to write a Redis script that will populate a list with N random
        integers.</p>
        
        <p>I can start with this small Ruby program:</p>
        
        <pre><code>require &#39;rubygems&#39;&#x000A;require &#39;redis&#39;&#x000A;&#x000A;r = Redis.new&#x000A;&#x000A;RandomPushScript = &lt;&lt;EOF&#x000A;    local i = tonumber(ARGV[1])&#x000A;    local res&#x000A;    while (i &gt; 0) do&#x000A;        res = redis.call(&#39;lpush&#39;,KEYS[1],math.random())&#x000A;        i = i-1&#x000A;    end&#x000A;    return res&#x000A;EOF&#x000A;&#x000A;r.del(:mylist)&#x000A;puts r.eval(RandomPushScript,[:mylist],[10,rand(2**32)])&#x000A;</code></pre>
        
        <p>Every time this script executed the resulting list will have exactly the
        following elements:</p>
        
        <pre><code>&gt; lrange mylist 0 -1&#x000A; 1) &quot;0.74509509873814&quot;&#x000A; 2) &quot;0.87390407681181&quot;&#x000A; 3) &quot;0.36876626981831&quot;&#x000A; 4) &quot;0.6921941534114&quot;&#x000A; 5) &quot;0.7857992587545&quot;&#x000A; 6) &quot;0.57730350670279&quot;&#x000A; 7) &quot;0.87046522734243&quot;&#x000A; 8) &quot;0.09637165539729&quot;&#x000A; 9) &quot;0.74990198051087&quot;&#x000A;10) &quot;0.17082803611217&quot;&#x000A;</code></pre>
        
        <p>In order to make it a pure function, but still be sure that every invocation
        of the script will result in different random elements, we can simply add an
        additional argument to the script that will be used in order to seed the Lua
        pseudo-random number generator.
        The new script is as follows:</p>
        
        <pre><code>RandomPushScript = &lt;&lt;EOF&#x000A;    local i = tonumber(ARGV[1])&#x000A;    local res&#x000A;    math.randomseed(tonumber(ARGV[2]))&#x000A;    while (i &gt; 0) do&#x000A;        res = redis.call(&#39;lpush&#39;,KEYS[1],math.random())&#x000A;        i = i-1&#x000A;    end&#x000A;    return res&#x000A;EOF&#x000A;&#x000A;r.del(:mylist)&#x000A;puts r.eval(RandomPushScript,1,:mylist,10,rand(2**32))&#x000A;</code></pre>
        
        <p>What we are doing here is sending the seed of the PRNG as one of the arguments.
        This way the script output will be the same given the same arguments, but we are
        changing one of the arguments in every invocation, generating the random seed
        client-side.
        The seed will be propagated as one of the arguments both in the replication
        link and in the Append Only File, guaranteeing that the same changes will be
        generated when the AOF is reloaded or when the slave processes the script.</p>
        
        <p>Note: an important part of this behavior is that the PRNG that Redis implements
        as <code>math.random</code> and <code>math.randomseed</code> is guaranteed to have the same output
        regardless of the architecture of the system running Redis.
        32-bit, 64-bit, big-endian and little-endian systems will all produce the same
        output.</p>
        
        <h2>Global variables protection</h2>
        
        <p>Redis scripts are not allowed to create global variables, in order to avoid
        leaking data into the Lua state.
        If a script needs to maintain state between calls (a pretty uncommon need) it
        should use Redis keys instead.</p>
        
        <p>When global variable access is attempted the script is terminated and EVAL
        returns with an error:</p>
        
        <pre><code>redis 127.0.0.1:6379&gt; eval &#39;a=10&#39; 0&#x000A;(error) ERR Error running script (call to f_933044db579a2f8fd45d8065f04a8d0249383e57): user_script:1: Script attempted to create global variable &#39;a&#39;&#x000A;</code></pre>
        
        <p>Accessing a <em>non existing</em> global variable generates a similar error.</p>
        
        <p>Using Lua debugging functionality or other approaches like altering the meta
        table used to implement global protections in order to circumvent globals
        protection is not hard.
        However it is difficult to do it accidentally.
        If the user messes with the Lua global state, the consistency of AOF and
        replication is not guaranteed: don&#39;t do it.</p>
        
        <p>Note for Lua newbies: in order to avoid using global variables in your scripts
        simply declare every variable you are going to use using the <em>local</em> keyword.</p>
        
        <h2>Available libraries</h2>
        
        <p>The Redis Lua interpreter loads the following Lua libraries:</p>
        
        <ul>
        <li>base lib.</li>
        <li>table lib.</li>
        <li>string lib.</li>
        <li>math lib.</li>
        <li>debug lib.</li>
        <li>cjson lib.</li>
        <li>cmsgpack lib.</li>
        </ul>
        
        <p>Every Redis instance is <em>guaranteed</em> to have all the above libraries so you can
        be sure that the environment for your Redis scripts is always the same.</p>
        
        <p>The CJSON library provides extremely fast JSON maniplation within Lua.
        All the other libraries are standard Lua libraries.</p>
        
        <h2>Emitting Redis logs from scripts</h2>
        
        <p>It is possible to write to the Redis log file from Lua scripts using the
        <code>redis.log</code> function.</p>
        
        <pre><code>redis.log(loglevel,message)&#x000A;</code></pre>
        
        <p><code>loglevel</code> is one of:</p>
        
        <ul>
        <li><code>redis.LOG_DEBUG</code></li>
        <li><code>redis.LOG_VERBOSE</code></li>
        <li><code>redis.LOG_NOTICE</code></li>
        <li><code>redis.LOG_WARNING</code></li>
        </ul>
        
        <p>They correspond directly to the normal Redis log levels.
        Only logs emitted by scripting using a log level that is equal or greater than
        the currently configured Redis instance log level will be emitted.</p>
        
        <p>The <code>message</code> argument is simply a string.
        Example:</p>
        
        <pre><code>redis.log(redis.LOG_WARNING,&quot;Something is wrong with this script.&quot;)&#x000A;</code></pre>
        
        <p>Will generate the following:</p>
        
        <pre><code>[32343] 22 Mar 15:21:39 # Something is wrong with this script.&#x000A;</code></pre>
        
        <h2>Sandbox and maximum execution time</h2>
        
        <p>Scripts should never try to access the external system, like the file system or
        any other system call.
        A script should only operate on Redis data and passed arguments.</p>
        
        <p>Scripts are also subject to a maximum execution time (five seconds by default).
        This default timeout is huge since a script should usually run in under a
        millisecond.
        The limit is mostly to handle accidental infinite loops created during
        development.</p>
        
        <p>It is possible to modify the maximum time a script can be executed with
        millisecond precision, either via <code>redis.conf</code> or using the CONFIG GET / CONFIG
        SET command.
        The configuration parameter affecting max execution time is called
        <code>lua-time-limit</code>.</p>
        
        <p>When a script reaches the timeout it is not automatically terminated by Redis
        since this violates the contract Redis has with the scripting engine to ensure
        that scripts are atomic.
        Interrupting a script means potentially leaving the dataset with half-written
        data.
        For this reasons when a script executes for more than the specified time the
        following happens:</p>
        
        <ul>
        <li>Redis logs that a script is running too long.</li>
        <li>It starts accepting commands again from other clients, but will reply with a
        BUSY error to all the clients sending normal commands.
        The only allowed commands in this status are <code>SCRIPT KILL</code> and <code>SHUTDOWN&#x000A;NOSAVE</code>.</li>
        <li>It is possible to terminate a script that executes only read-only commands
        using the <code>SCRIPT KILL</code> command.
        This does not violate the scripting semantic as no data was yet written to the
        dataset by the script.</li>
        <li>If the script already called write commands the only allowed command becomes
        <code>SHUTDOWN NOSAVE</code> that stops the server without saving the current data set on
        disk (basically the server is aborted).</li>
        </ul>
        
        <h2>EVALSHA in the context of pipelining</h2>
        
        <p>Care should be taken when executing <a href="/commands/evalsha.html">EVALSHA</a> in the context of a pipelined
        request, since even in a pipeline the order of execution of commands must be
        guaranteed.
        If <a href="/commands/evalsha.html">EVALSHA</a> will return a <code>NOSCRIPT</code> error the command can not be reissued
        later otherwise the order of execution is violated.</p>
        
        <p>The client library implementation should take one of the following approaches:</p>
        
        <ul>
        <li><p>Always use plain <a href="/commands/eval.html">EVAL</a> when in the context of a pipeline.</p></li>
        <li><p>Accumulate all the commands to send into the pipeline, then check for <a href="/commands/eval.html">EVAL</a>
        commands and use the <code>SCRIPT EXISTS</code> command to check if all the scripts are
        already defined.
        If not, add <code>SCRIPT LOAD</code> commands on top of the pipeline as required, and
        use <a href="/commands/evalsha.html">EVALSHA</a> for all the <a href="/commands/eval.html">EVAL</a> calls.</p></li>
        </ul>
        
      </article>
    </div>
    <script type='text/javascript'>startShow();</script>
    <div class='text' id='comments'>
      <div id='disqus_thread'></div>
      <script type='text/javascript'>
        //<![CDATA[
          var disqus_shortname = 'rediscn';
          
          // The following are highly recommended additional parameters. Remove the slashes in front to use.
          var disqus_identifier = 'command_'+curCommandObj.key;
          var disqus_url = curCommandObj.getdisqusUrl();  // = 'http://redis.cn/commands/'+curCommandObj.key;
          
          /* * * DON'T EDIT BELOW THIS LINE * * */
          (function() {
            var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
              dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
              (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
          })();
        //]]>
      </script>
      <a class='dsq-brlink' href='http://disqus.com'>
        Comments powered by
        <span class='logo-disqus'>
          Disqus
        </span>
      </a>
    </div>

    
    <script src='/js/foot.js'></script>
    
  </body>
</html>
